package com.gitee.wsl.ext.string

/**
 * Puts the string [with] before and after the string
 */
fun String.surround(with: String) = "$with${this}$with"


// withPrefix / withSuffix ---------------------------------------------------------------------------------------------

/** Returns this char with the [prefix] prepended if it's not already present. */
public fun kotlin.Char.withPrefix(prefix: CharSequence): String =
    toString().withPrefix(prefix)

/** Returns this char with the [suffix] appended if it's not already present. */
public fun kotlin.Char.withSuffix(suffix: CharSequence): String =
    toString().withSuffix(suffix)

/** Returns this character sequence with the [prefix] prepended if it's not already present. */
public fun CharSequence.withPrefix(prefix: CharSequence): CharSequence =
    if (startsWith(prefix)) this else buildString { append(prefix); append(this@withPrefix) }

/** Returns this character sequence with the [suffix] appended if it's not already present. */
public fun CharSequence.withSuffix(suffix: CharSequence): CharSequence =
    if (endsWith(suffix)) this else buildString { append(this@withSuffix);append(suffix) }

/** Returns this string with the [prefix] prepended if it's not already present. */
public fun String.withPrefix(prefix: CharSequence): String =
    if (startsWith(prefix)) this else buildString { append(prefix); append(this@withPrefix) }

/** Returns this string with the [suffix] appended if it's not already present. */
public fun String.withSuffix(suffix: CharSequence): String =
    if (endsWith(suffix)) this else buildString { append(this@withSuffix);append(suffix) }


// withRandomSuffix ----------------------------------------------------------------------------------------------------

private const val randomSuffixLength = 4
private const val randomSuffixSeparator = "--"

@Suppress("RegExpSimplifiable")
private val randomSuffixMatcher: Regex = Regex(".*$randomSuffixSeparator[\\da-zA-Z]{$randomSuffixLength}\$")

/** Returns this char with a random suffix of two dashes and four alphanumeric characters. */
public fun kotlin.Char.withRandomSuffix(): String =
    toString().withRandomSuffix()

/** Returns this character sequence with a random suffix of two dashes and four alphanumeric characters. */
public fun CharSequence.withRandomSuffix(): CharSequence =
    if (randomSuffixMatcher.matches(this)) this
    else buildString { append(this@withRandomSuffix); append(randomSuffixSeparator); append(randomString(length = randomSuffixLength)) }

/** Returns this string with a random suffix of two dashes and four alphanumeric characters. */
public fun String.withRandomSuffix(): String =
    if (randomSuffixMatcher.matches(this)) this
    else buildString { append(this@withRandomSuffix); append(randomSuffixSeparator); append(randomString(length = randomSuffixLength)) }


// ------------------------------------------------------------------------ strip
/**
 * 去除两边的指定字符串，忽略大小写
 *
 * @param str            被处理的字符串
 * @param prefixOrSuffix 前缀或后缀
 * @return 处理后的字符串
 * @since 3.1.2
 */
fun CharSequence.stripIgnoreCase(prefixOrSuffix: CharSequence): String {
    return stripIgnoreCase( prefixOrSuffix, prefixOrSuffix)
}

/**
 * 去除两边的指定字符串，忽略大小写
 *
 * @param str    被处理的字符串
 * @param prefix 前缀
 * @param suffix 后缀
 * @return 处理后的字符串
 * @since 3.1.2
 */
fun CharSequence.stripIgnoreCase(prefix: CharSequence, suffix: CharSequence): String {
    return strip( prefix, suffix, true)
}

/**
 * 去除两边的指定字符串
 *
 * @param str            被处理的字符串
 * @param prefixOrSuffix 前缀或后缀
 * @return 处理后的字符串
 * @since 3.1.2
 */
fun CharSequence.strip( prefixOrSuffix: CharSequence): String {
    if (this == prefixOrSuffix) {
        // 对于去除相同字符的情况单独处理
        return String.EMPTY
    }
    return strip( prefixOrSuffix, prefixOrSuffix)
}

/**
 * 去除两边的指定字符串<br></br>
 * 两边字符如果存在，则去除，不存在不做处理
 * <pre>`"aaa_STRIPPED_bbb", "a", "b"  -> "aa_STRIPPED_bb"
 * "aaa_STRIPPED_bbb", null, null  -> "aaa_STRIPPED_bbb"
 * "aaa_STRIPPED_bbb", "", ""  -> "aaa_STRIPPED_bbb"
 * "aaa_STRIPPED_bbb", "", "b"  -> "aaa_STRIPPED_bb"
 * "aaa_STRIPPED_bbb", null, "b"  -> "aaa_STRIPPED_bb"
 * "aaa_STRIPPED_bbb", "a", ""  -> "aa_STRIPPED_bbb"
 * "aaa_STRIPPED_bbb", "a", null  -> "aa_STRIPPED_bbb"
 *
 * "a", "a", "a"  -> ""
` *
</pre> *
 *
 * @param str    被处理的字符串
 * @param prefix 前缀
 * @param suffix 后缀
 * @return 处理后的字符串
 * @since 3.1.2
 */
fun CharSequence.strip( prefix: CharSequence, suffix: CharSequence): String {
    return strip(prefix, suffix, false)
}

/**
 * 去除两边的指定字符串<br></br>
 * 两边字符如果存在，则去除，不存在不做处理
 * <pre>`"aaa_STRIPPED_bbb", "a", "b"  -> "aa_STRIPPED_bb"
 * "aaa_STRIPPED_bbb", null, null  -> "aaa_STRIPPED_bbb"
 * "aaa_STRIPPED_bbb", "", ""  -> "aaa_STRIPPED_bbb"
 * "aaa_STRIPPED_bbb", "", "b"  -> "aaa_STRIPPED_bb"
 * "aaa_STRIPPED_bbb", null, "b"  -> "aaa_STRIPPED_bb"
 * "aaa_STRIPPED_bbb", "a", ""  -> "aa_STRIPPED_bbb"
 * "aaa_STRIPPED_bbb", "a", null  -> "aa_STRIPPED_bbb"
 *
 * "a", "a", "a"  -> ""
` *
</pre> *
 *
 * @param str    被处理的字符串
 * @param prefix 前缀
 * @param suffix 后缀
 * @param ignoreCase 是否忽略大小写
 * @return 处理后的字符串
 * @since 3.1.2
 */
fun CharSequence.strip( prefix: CharSequence, suffix: CharSequence, ignoreCase: Boolean): String {
    val str=this
    if (str.isEmpty()) {
        return str.toString()
    }

    val str2 = str.toString()
    var from = 0
    var to = str2.length

    if (str2.startsWith(prefix, ignoreCase)) {
        from = prefix.length
        if (from == to) {
            // "a", "a", "a"  -> ""
            return String.EMPTY
        }
    }
    if (str2.endsWith(suffix, ignoreCase)) {
        to -= suffix.length
        if (from == to) {
            // "a", "a", "a"  -> ""
            return String.EMPTY
        } else if (to < from) {
            // pre去除后和suffix有重叠，如 ("aba", "ab", "ba") -> "a"
            to += suffix.length
        }
    }

    return str2.substring(from, to)
}

/**
 * 去除两边<u>**所有**</u>的指定字符串
 *
 * <pre>`"aaa_STRIPPED_bbb", "a"  -> "_STRIPPED_bbb"
 * "aaa_STRIPPED_bbb", "a", "b"  -> "_STRIPPED_"
 * "aaa_STRIPPED_bbb", ""  -> "aaa_STRIPPED_bbb"
` *
</pre> *
 *
 * @param str            被处理的字符串
 * @param prefixOrSuffix 前缀或后缀
 * @return 处理后的字符串
 * @since 5.8.30
 */
fun CharSequence.stripAll( prefixOrSuffix: CharSequence): String {
    if (this == prefixOrSuffix) {
        return String.EMPTY
    }
    return stripAll( prefixOrSuffix, prefixOrSuffix)
}

/**
 * 去除两边<u>**所有**</u>的指定字符串
 *
 * <pre>`"aaa_STRIPPED_bbb", "a", "b"  -> "_STRIPPED_"
 * "aaa_STRIPPED_bbb", null, null  -> "aaa_STRIPPED_bbb"
 * "aaa_STRIPPED_bbb", "", ""  -> "aaa_STRIPPED_bbb"
 * "aaa_STRIPPED_bbb", "", "b"  -> "aaa_STRIPPED_"
 * "aaa_STRIPPED_bbb", null, "b"  -> "aaa_STRIPPED_"
 * "aaa_STRIPPED_bbb", "a", ""  -> "_STRIPPED_bbb"
 * "aaa_STRIPPED_bbb", "a", null  -> "_STRIPPED_bbb"
 *
 * // special test
 * "aaaaaabbb", "aaa", null  -> "bbb"
 * "aaaaaaabbb", "aa", null  -> "abbb"
 *
 * "aaaaaaaaa", "aaa", "aa"  -> ""
 * "a", "a", "a"  -> ""
` *
</pre> *
 *
 * @param str    被处理的字符串
 * @param prefix 前缀
 * @param suffix 后缀
 * @return 处理后的字符串
 * @since 5.8.30
 */
fun CharSequence.stripAll( prefix: CharSequence, suffix: CharSequence?): String {
    val str = this
    if (str.isEmpty()) {
        return str.toString()
    }

    val prefixStr: String = prefix.toString()
    val suffixStr: String = suffix?.toString()?:String.EMPTY

    val str2 = str.toString()
    var from = 0
    var to = str2.length

    if (!prefixStr.isEmpty()) {
        while (str2.startsWith(prefixStr, from)) {
            from += prefix.length
            if (from == to) {
                // "a", "a", "a"  -> ""
                return String.EMPTY
            }
        }
    }
    if (!suffixStr.isEmpty()) {
        while (str2.startsWith(suffixStr, to - suffixStr.length)) {
            to -= suffixStr.length
            if (from == to) {
                // "a", "a", "a"  -> ""
                return String.EMPTY
            } else if (to < from) {
                // pre去除后和suffix有重叠，如 ("aba", "ab", "ba") -> "a"
                to += suffixStr.length
                break
            }
        }
    }

    return str2.substring(from, to)
}

/**
 * 给定字符串是否被字符包围
 *
 * @param str    字符串
 * @param prefix 前缀
 * @param suffix 后缀
 * @return 是否包围，空串不包围
 */
fun CharSequence.isSurround( prefix: CharSequence, suffix: CharSequence): Boolean {
    if (isBlank()) {
        return false
    }
    if (length < (prefix.length + suffix.length)) {
        return false
    }

    val str2 = toString()
    return str2.startsWith(prefix.toString()) && str2.endsWith(suffix.toString())
}

/**
 * 给定字符串是否被字符包围
 *
 * @param str    字符串
 * @param prefix 前缀
 * @param suffix 后缀
 * @return 是否包围，空串不包围
 */
fun CharSequence.isSurround( prefix: Char, suffix: Char): Boolean {
    if (isBlank()) {
        return false
    }
    if (length < 2) {
        return false
    }

    return get(0) == prefix && get(length - 1) == suffix
}
